package com.uduemc.biso.node.web.api.service.impl;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.uduemc.biso.core.extities.pojo.DeployType;
import com.uduemc.biso.core.utils.RedisUtil;
import com.uduemc.biso.node.core.common.entities.ThemeObject;
import com.uduemc.biso.node.core.common.entities.themeobject.ThemeObjectHtmlTag;
import com.uduemc.biso.node.core.common.entities.themeobject.ThemeObjectHtmlTagAttrs;
import com.uduemc.biso.node.core.common.entities.themeobject.ThemeObjectSource;
import com.uduemc.biso.node.core.common.exception.TemplateException;
import com.uduemc.biso.node.core.common.themepojo.ThemeColor;
import com.uduemc.biso.node.core.common.utils.ThemeUtil;
import com.uduemc.biso.node.core.entities.SConfig;
import com.uduemc.biso.node.core.property.GlobalProperties;
import com.uduemc.biso.node.web.api.component.RequestHolder;
import com.uduemc.biso.node.web.api.component.SiteHolder;
import com.uduemc.biso.node.web.api.config.SpringContextUtil;
import com.uduemc.biso.node.web.api.service.SConfigService;
import com.uduemc.biso.node.web.api.service.ThemeService;
import com.uduemc.biso.node.web.service.DeployService;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;

@Service
public class ThemeServiceImpl implements ThemeService {

	public static String DEV_BACKEND_JS = "http://localhost:2399/backendjs.js";
	public static String[] AUTHOR = { "all", "backend" };

	// 定义 ThemeObject.mapping 默认数据，${no} 为 ThemeObject.no
	public static Map<String, String> MAPPING = new HashMap<>();
	static {
		MAPPING.put("index", "biso-assets/static/site/np_template/${no}/index.html");
		MAPPING.put("list", "biso-assets/static/site/np_template/${no}/news_list.html");
		MAPPING.put("article", "biso-assets/static/site/np_template/${no}/news_detail.html");
		MAPPING.put("cate", "biso-assets/static/site/np_template/${no}/product_list.html");
		MAPPING.put("product", "biso-assets/static/site/np_template/${no}/product_detail.html");
		MAPPING.put("downlist", "biso-assets/static/site/np_template/${no}/product_list.html");
		MAPPING.put("faqitem", "biso-assets/static/site/np_template/${no}/product_detail.html");
		MAPPING.put("faqlist", "biso-assets/static/site/np_template/${no}/product_list.html");
		MAPPING.put("informationlist", "biso-assets/static/site/np_template/${no}/product_list.html");
		MAPPING.put("informationitem", "biso-assets/static/site/np_template/${no}/product_detail.html");
		MAPPING.put("pdtablelist", "biso-assets/static/site/np_template/${no}/product_list.html");
		MAPPING.put("pdtableitem", "biso-assets/static/site/np_template/${no}/product_detail.html");
	}

	@Autowired
	RedisUtil redisUtil;

	@Autowired
	RequestHolder requestHolder;

	@Autowired
	SiteHolder siteHolder;

	@Autowired
	GlobalProperties globalProperties;

	@Autowired
	SConfigService sConfigServiceImpl;

	@Autowired
	ObjectMapper objectMapper;

	@Autowired
	SpringContextUtil springContextUtil;

	@Autowired
	DeployService deployServiceImpl;

	@Override
	public String getThemeJson() throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		if (siteHolder != null && siteHolder.getSiteConfig() != null && siteHolder.getSiteConfig().getSConfig() != null) {
			String theme = siteHolder.getSiteConfig().getSConfig().getTheme();
			return getThemeJson(theme);
		} else {
			Long id = requestHolder.getCurrentSite().getId();
			return getThemeJson(id);
		}
	}

	@Override
	public String getThemeJson(long siteId) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		SConfig sConfig = sConfigServiceImpl.getInfoBySiteId(siteId);
		return getThemeJson(sConfig.getTheme());
	}

	@Override
	public String getThemeJson(String theme) {
		String assetsPath = globalProperties.getSite().getAssetsPath();
		String redisPackageJson = ThemeUtil.getThemeJson(assetsPath, theme);
		return redisPackageJson;
//		String redisKey = globalProperties.getRedisKey().getThemeJson(theme);
//		String redisPackageJson = (String) redisUtil.get(redisKey);
//		if (!springContextUtil.prod() || StrUtil.isBlank(redisPackageJson)) {
//			try {
//				String assetsPath = globalProperties.getSite().getAssetsPath();
//				redisPackageJson = ThemeUtil.getThemeJson(assetsPath, theme);
//				if (!StringUtils.isEmpty(redisPackageJson)) {
//					redisUtil.set(redisKey, redisPackageJson, 3600 * 24 * 10L);
//				}
//			} catch (TemplateException e) {
//				e.printStackTrace();
//			}
//		}
//		return redisPackageJson;
	}

	@Override
	public ThemeObject getThemeObject() throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		if (siteHolder != null && siteHolder.getSiteConfig() != null && siteHolder.getSiteConfig().getSConfig() != null) {
			String theme = siteHolder.getSiteConfig().getSConfig().getTheme();
			return getThemeObject(theme);
		} else {
			Long id = requestHolder.getCurrentSite().getId();
			return getThemeObject(id);
		}
	}

	@Override
	public ThemeObject getThemeObject(long siteId) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		SConfig sConfig = sConfigServiceImpl.getInfoBySiteId(siteId);
		return getThemeObject(sConfig.getTheme());
	}

	@Override
	public ThemeObject getThemeObject(String theme) throws JsonParseException, JsonMappingException, IOException {
		String redisKey = globalProperties.getRedisKey().getThemeJsonObject(theme);
		ThemeObject themeObject = (ThemeObject) redisUtil.get(redisKey);
		if (!springContextUtil.prod() || themeObject == null) {
			String themeJson = getThemeJson(theme);
			themeObject = objectMapper.readValue(themeJson, ThemeObject.class);
			// 初始化 mapping 的动作
			Map<String, String> mapping = themeObject.getMapping();
			Map<String, String> nmapping = new HashMap<>();
			if (MapUtil.isEmpty(mapping)) {
				for (String key : MAPPING.keySet()) {
					nmapping.put(key, StrUtil.replace(MAPPING.get(key), "${no}", themeObject.getNo()));
				}
			} else {
				for (String key : MAPPING.keySet()) {
					if (StrUtil.isNotBlank(mapping.get(key))) {
						nmapping.put(key, mapping.get(key));
					} else {
						nmapping.put(key, StrUtil.replace(MAPPING.get(key), "${no}", themeObject.getNo()));
					}
				}
			}
			themeObject.setMapping(nmapping);

			if (themeObject != null) {
				redisUtil.set(redisKey, themeObject, 3600 * 24 * 10L);
			}
		}
		return themeObject;
	}

	@Override
	public Map<String, ThemeColor> getAllNPThemeColorData() throws IOException {
		String redisKey = globalProperties.getRedisKey().getThemeNPColor();
		@SuppressWarnings("unchecked")
		Map<String, ThemeColor> result = (Map<String, ThemeColor>) redisUtil.get(redisKey);
		if (!springContextUtil.prod() || result == null) {
			result = new HashMap<String, ThemeColor>();
			// 从文件中读取内容
			String assetsPath = globalProperties.getSite().getAssetsPath();
			StringBuilder filedir = new StringBuilder(assetsPath);
			filedir.append("/static/site/np_template/模板颜色.txt");
			String filePath = filedir.toString();
			String readFileToString = FileUtils.readFileToString(new File(filePath), "UTF-8");
			String[] splitFileToString = readFileToString.split("\n");
			if (splitFileToString.length > 0) {
				for (String line : splitFileToString) {
					line = StringUtils.trimWhitespace(line);
					if (StringUtils.hasText(line)) {
						int indexOf = line.indexOf("/");
						String num = line.substring(0, indexOf);
						try {
							Integer.valueOf(num);
						} catch (NumberFormatException e) {
							continue;
						}
						Pattern pattern = Pattern.compile("(#(\\w{6}|\\w{3}))");
						Matcher matcher = pattern.matcher(line);

						ThemeColor themeColor = new ThemeColor();
						List<String> listColor = new ArrayList<>();
						while (matcher.find()) {
							listColor.add(matcher.group(1));
						}
						themeColor.setColor(listColor).setNpno(num);
						result.put(num, themeColor);
					}
				}
			}
			if (result != null) {
				redisUtil.set(redisKey, result, 3600 * 24 * 1L);
			}
		}
		return result;
	}

	@Override
	public ThemeColor getThemeColorByTheme(String theme) throws IOException {
		ThemeObject themeObject = getThemeObject(theme);
		String npno = themeObject.getNo();
		return getThemeColorByNpNo(npno);
	}

	protected ThemeColor getThemeColorByNpNo(String npno) throws IOException {
		Map<String, ThemeColor> allNPThemeColorData = getAllNPThemeColorData();
		return allNPThemeColorData.get(npno);
	}

	@Override
	public String getThemeColorCssByTheme(String theme, int colorIndex) throws IOException {
		ThemeObject themeObject = getThemeObject(theme);
		return getThemeColorCssByNpNo(themeObject, colorIndex);
	}

	protected String getThemeColorCssByNpNo(ThemeObject themeObject, int colorIndex) throws IOException {
		String npno = themeObject.getNo();
		String assetsPath = globalProperties.getSite().getAssetsPath();
		StringBuilder filedir = new StringBuilder(assetsPath);
		filedir.append("/static/site/np_template/" + npno + "/css/color_" + colorIndex + ".css");
		String filePath = filedir.toString();
		String readFileToString = FileUtils.readFileToString(new File(filePath), "UTF-8");
		return readFileToString;
	}

	@Override
	public List<ThemeObject> getAllThemeObject() throws IOException {
		String assetsPath = globalProperties.getSite().getAssetsPath();
		List<String> allTemplateTheme = ThemeUtil.getAllThemeJson(assetsPath);
		List<ThemeObject> result = new ArrayList<>();
		for (String theme : allTemplateTheme) {
			result.add(getThemeObject(theme));
		}
		return result;
	}

	@Override
	public String getThemeHead() throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		String theme = null;
		if (siteHolder != null && siteHolder.getSiteConfig() != null && siteHolder.getSiteConfig().getSConfig() != null) {
			theme = siteHolder.getSiteConfig().getSConfig().getTheme();
		} else {
			Long siteId = requestHolder.getCurrentSite().getId();
			SConfig sConfig = sConfigServiceImpl.getInfoBySiteId(siteId);
			theme = sConfig.getTheme();
		}
		if (StrUtil.isBlank(theme)) {
			throw new TemplateException("theme 为空，无法正确匹配模板！");
		}
		return getThemeHead(theme);
	}

	@Override
	public String getThemeHead(String theme) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		if (siteHolder != null && siteHolder.getSitePage() != null && StrUtil.isNotBlank(siteHolder.getSitePage().getTemplateName())) {
			return getThemeHead(theme, siteHolder.getSitePage().getTemplateName());
		}

		throw new TemplateException("页面的 templateName 为空，无法正确匹配模板！");
	}

	@Override
	public String getThemeHead(String theme, String templateName) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		String redisKey = globalProperties.getRedisKey().getThemeHtmlHead(theme, templateName);
		String result = (String) redisUtil.get(redisKey);
		if (!springContextUtil.prod() || StrUtil.isBlank(result)) {
			ThemeObject themeObject = getThemeObject(theme);
			result = ThemeUtil.getThemeHead(themeObject, templateName, globalProperties.getSite().getAssetsPath());
			if (result != null) {
				redisUtil.set(redisKey, result, 3600 * 24 * 10L);
			}
		}
		return result;
	}

	@Override
	public String getThemeBody() throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		String theme = null;
		if (siteHolder != null && siteHolder.getSiteConfig() != null && siteHolder.getSiteConfig().getSConfig() != null) {
			theme = siteHolder.getSiteConfig().getSConfig().getTheme();
		} else {
			Long siteId = requestHolder.getCurrentSite().getId();
			SConfig sConfig = sConfigServiceImpl.getInfoBySiteId(siteId);
			theme = sConfig.getTheme();
		}
		if (StrUtil.isBlank(theme)) {
			throw new TemplateException("theme 为空，无法正确匹配模板！");
		}
		return getThemeBody(theme);
	}

	@Override
	public String getThemeBody(String theme) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		if (siteHolder != null && siteHolder.getSitePage() != null && StrUtil.isNotBlank(siteHolder.getSitePage().getTemplateName())) {
			return getThemeBody(theme, siteHolder.getSitePage().getTemplateName());
		}

		throw new TemplateException("页面的 templateName 为空，无法正确匹配模板！");
	}

	@Override
	public String getThemeBody(String theme, String templateName) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		String redisKey = globalProperties.getRedisKey().getThemeHtmlBody(theme, templateName);
		String result = (String) redisUtil.get(redisKey);
		if (!springContextUtil.prod() || StrUtil.isBlank(result)) {
			ThemeObject themeObject = getThemeObject(theme);
			result = ThemeUtil.getThemeBody(themeObject, templateName, globalProperties.getSite().getAssetsPath());
			if (result != null) {
				redisUtil.set(redisKey, result, 3600 * 24 * 10L);
			}
		}
		return result;
	}

	@Override
	public StringBuilder makeSRBackendHead() throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		ThemeObject themeObject = getThemeObject();
		if (themeObject == null) {
			return new StringBuilder("<!-- themeObject 内容为空 -->");
		}
		List<ThemeObjectSource> head = themeObject.getHead();
		if (CollectionUtil.isEmpty(head)) {
			return new StringBuilder("<!-- head 内容为空 -->");
		}
		return makeThemeObjectSource(head);
	}

	@Override
	public StringBuilder makeSRBackendBeginBody() throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		ThemeObject themeObject = getThemeObject();
		if (themeObject == null) {
			return new StringBuilder("<!-- themeObject 内容为空 -->");
		}
		List<ThemeObjectSource> beginBody = themeObject.getBeginBody();
		if (CollectionUtil.isEmpty(beginBody)) {
			return new StringBuilder("<!-- beginBody 内容为空 -->");
		}
		return makeThemeObjectSource(beginBody);
	}

	@Override
	public StringBuilder makeSRBackendEndBody() throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		ThemeObject themeObject = getThemeObject();
		if (themeObject == null) {
			return new StringBuilder("<!-- themeObject 内容为空 -->");
		}
		List<ThemeObjectSource> endBody = themeObject.getEndBody();
		if (CollectionUtil.isEmpty(endBody)) {
			return new StringBuilder("<!-- endBody 内容为空 -->");
		}
		return makeThemeObjectSource(endBody);
	}

	@Override
	public StringBuilder makeThemeMeta() throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		String theme = null;
		if (siteHolder != null && siteHolder.getSiteConfig() != null && siteHolder.getSiteConfig().getSConfig() != null) {
			theme = siteHolder.getSiteConfig().getSConfig().getTheme();
		} else {
			Long siteId = requestHolder.getCurrentSite().getId();
			SConfig sConfig = sConfigServiceImpl.getInfoBySiteId(siteId);
			theme = sConfig.getTheme();
		}
		if (StrUtil.isBlank(theme)) {
			return new StringBuilder("<!-- 未能获取到 theme -->");
		}
		return makeThemeMeta(theme);
	}

	@Override
	public StringBuilder makeThemeMeta(String theme) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		StringBuilder make = new StringBuilder("<!-- ThemeMeta -->");
		// 根据模板中的 head <meta 标签写入 head 中
		Pattern pattern = Pattern.compile("<meta.*?>", Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
		Matcher matcher = pattern.matcher(getThemeHead(theme));
		while (matcher.find()) {
			String meta = matcher.group(0);
			make.append("\n" + meta);
		}
		return make;
	}

	@Override
	public StringBuilder makeTitle() {
		StringBuilder make = new StringBuilder("\n" + "<!-- Title -->");
		if (siteHolder != null && siteHolder.getSitePage() != null && StrUtil.isNotBlank(siteHolder.getSitePage().getTemplateName())) {
			make.append("\n" + "<title>" + siteHolder.getSitePage().getSPage().getName() + "</title>");
		} else {
			make.append("\n" + "<title></title>");
		}
		return make;
	}

	@Override
	public StringBuilder makeDynamicMeta() {
		StringBuilder make = new StringBuilder("\n" + "<!-- 目前后台对 <DynamicMeta> 不做解释 -->");
		return make;
	}

	@Override
	public StringBuilder makeComponentsjsSource() throws IOException {
		StringBuilder make = new StringBuilder("\n" + "<!-- ComponentsjsSource -->");
		String componentjsVersion = deployServiceImpl.localhostVersion(DeployType.COMPONENTS);
		String componentsCss = "/api/deploy/components/dist-udin.css?v=" + componentjsVersion;
		String componentsJS = "/api/deploy/components/dist-udin.js?v=" + componentjsVersion;

		String three = ThemeUtil.getBackendHref(siteHolder.getHost().getId(), siteHolder.getSite().getId(), "/assets/static/site/np_template/js/three.min.js");

		make.append("\n<script type=\"text/javascript\" src=\"" + three + "\"></script>");
		make.append("\n<link type=\"text/css\" rel=\"stylesheet\" href=\"" + componentsCss + "\" />");
		make.append("\n<script type=\"text/javascript\" src=\"" + componentsJS + "\"></script>");
		return make;
	}

	@Override
	public StringBuilder makeThemeSource() throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		String theme = null;
		String color = null;
		if (siteHolder != null && siteHolder.getSiteConfig() != null && siteHolder.getSiteConfig().getSConfig() != null) {
			theme = siteHolder.getSiteConfig().getSConfig().getTheme();
			color = siteHolder.getSiteConfig().getSConfig().getColor();
		} else {
			Long siteId = requestHolder.getCurrentSite().getId();
			SConfig sConfig = sConfigServiceImpl.getInfoBySiteId(siteId);
			theme = sConfig.getTheme();
			color = sConfig.getColor();
		}
		if (StrUtil.isBlank(theme)) {
			return new StringBuilder("\n" + "<!-- 未能获取到 theme -->");
		}
		return makeThemeSource(theme, color);
	}

	@Override
	public StringBuilder makeThemeSource(String theme, String color) {
		StringBuilder make = new StringBuilder("\n" + "<!-- ThemeSource -->");
		String colorLink = "/assets/static/site/np_template/" + theme + "/css/color_" + color + ".css";
		if (!NumberUtil.isNumber(color)) {
			colorLink += "?t=" + (System.currentTimeMillis());
		}
		String[] link = { "/assets/static/site/np_template/" + theme + "/css/theme.css", colorLink };
		for (String str : link) {
			make.append("\n" + "<link type=\"text/css\" rel=\"stylesheet\" href=\""
					+ ThemeUtil.getBackendHref(siteHolder.getHost().getId(), siteHolder.getSite().getId(), str) + "\">");
		}
		String[] script = { "/assets/static/site/np_template/" + theme + "/js/theme.js" };
		for (String str : script) {
			make.append("\n" + "<script type=\"text/javascript\" src=\""
					+ ThemeUtil.getBackendHref(siteHolder.getHost().getId(), siteHolder.getSite().getId(), str) + "\"></script>");
		}
		return make;
	}

	@Override
	public StringBuilder makeBackendjsSource() throws IOException {
		StringBuilder stringBuilder = new StringBuilder("\n" + "<!-- BackendjsSource -->");
		if (springContextUtil.local()) {
			stringBuilder.append("\n<script type=\"text/javascript\" src=\"" + ThemeServiceImpl.DEV_BACKEND_JS + "\"></script>");
		} else {
			String backendjsVersion = deployServiceImpl.localhostVersion(DeployType.BACKENDJS);
			String backendjsCss = "/api/deploy/backendjs/backend.css?v=" + backendjsVersion;
			String backendjsJS = "/api/deploy/backendjs/backend.js?v=" + backendjsVersion;
			stringBuilder.append("\n<link type=\"text/css\" rel=\"stylesheet\" href=\"" + backendjsCss + "\" />");
			stringBuilder.append("\n<script type=\"text/javascript\" src=\"" + backendjsJS + "\"></script>");
		}

		return stringBuilder;
	}

	@Override
	public StringBuilder makeSourceTags(List<ThemeObjectHtmlTag> source) throws IOException {
		StringBuilder stringBuilder = new StringBuilder("\n" + "<!-- SourceTags -->");
		if (CollectionUtil.isEmpty(source)) {
			return stringBuilder;
		}
		stringBuilder.append(makeThemeObjectHtmlTag(source));
		return stringBuilder;
	}

	@Override
	public StringBuilder makeInclude(String type) throws JsonParseException, JsonMappingException, IOException {
		StringBuilder stringBuilder = new StringBuilder("\n" + "<!-- Include Source -->");
		Pattern pattern = Pattern.compile("<Include:(.*)>");
		Matcher matcher = pattern.matcher(type);
		String sourceSrc = null;
		if (matcher.find()) {
			sourceSrc = StrUtil.trim(matcher.group(1));
		}
		if (StrUtil.isBlank(sourceSrc)) {
			stringBuilder.append("\n" + "<!-- SourceSrc Empty! type: " + type + " -->");
			return stringBuilder;
		}
		String source = ThemeUtil.getInclude(sourceSrc, globalProperties.getSite().getAssetsPath());
		if (StrUtil.isBlank(source)) {
			stringBuilder.append("\n" + "<!-- Source Empty! type: " + type + " -->");
			return stringBuilder;
		}

		@SuppressWarnings("unused")
		List<ThemeObjectHtmlTag> themeObjectHtmlTagList = objectMapper.readValue(source, new TypeReference<List<ThemeObjectHtmlTag>>() {
		});
		if (CollectionUtil.isEmpty(themeObjectHtmlTagList)) {
			stringBuilder.append("\n" + "<!-- List<ThemeObjectHtmlTag> Empty! type: " + type + " -->");
			return stringBuilder;
		}
		stringBuilder.append(makeThemeObjectHtmlTag(themeObjectHtmlTagList));
		return stringBuilder;
	}

	private StringBuilder makeThemeObjectHtmlTag(List<ThemeObjectHtmlTag> list) {
		StringBuilder stringBuilder = new StringBuilder();
		if (CollectionUtil.isEmpty(list)) {
			return stringBuilder;
		}

		for (ThemeObjectHtmlTag themeObjectHtmlTag : list) {
			String tag = themeObjectHtmlTag.getTag();
			if (tag.equals("<NULL>")) {
				stringBuilder.append("\n" + themeObjectHtmlTag.getContent());
			} else {
				if (StrUtil.isBlank(tag)) {
					continue;
				}
				StringBuilder tagHtml = new StringBuilder("\n" + "<" + tag);
				List<ThemeObjectHtmlTagAttrs> attrs = themeObjectHtmlTag.getAttrs();
				if (!CollectionUtil.isEmpty(attrs)) {
					for (ThemeObjectHtmlTagAttrs attr : attrs) {
						String name = attr.getName();
						String value = attr.getValue();
						if (tag.equals("link") && name.equals("href") && themeObjectHtmlTag.getPrefix() != null && themeObjectHtmlTag.getPrefix() == true) {
							value = ThemeUtil.getBackendHref(siteHolder.getHost().getId(), siteHolder.getSite().getId(), value);
						} else if (tag.equals("script") && name.equals("src") && themeObjectHtmlTag.getPrefix() != null
								&& themeObjectHtmlTag.getPrefix() == true) {
							value = ThemeUtil.getBackendHref(siteHolder.getHost().getId(), siteHolder.getSite().getId(), value);
						}
						tagHtml.append(" " + name + "=\"" + value + "\"");
					}
				}
				boolean vod = themeObjectHtmlTag.getVod() == null ? true : themeObjectHtmlTag.getVod();
				if (tag.equals("link")) {
					vod = true;
				} else if (tag.equals("script")) {
					vod = false;
				}

				if (vod) {
					tagHtml.append(" />");
				} else {
					String content = themeObjectHtmlTag.getContent();
					tagHtml.append(">" + (StrUtil.isBlank(content) ? "" : "\n" + content + "\n") + "</" + tag + ">");
				}
				stringBuilder.append(tagHtml.toString());
			}
		}
		return stringBuilder;
	}

	@Override
	public StringBuilder makeThemeObjectSource(List<ThemeObjectSource> list)
			throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		StringBuilder result = new StringBuilder();
		for (ThemeObjectSource themeObjectSource : list) {
			String author = themeObjectSource.getAuthor();
			if (!ArrayUtil.<String>contains(AUTHOR, author)) {
				continue;
			}
			String type = themeObjectSource.getType();
			if (type.equals("<ThemeMeta>")) {
				result.append(makeThemeMeta());
			} else if (type.equals("<Title>")) {
				result.append(makeTitle());
			} else if (type.equals("<DynamicMeta>")) {
				result.append(makeDynamicMeta());
			} else if (type.equals("<ComponentsjsSource>")) {
				result.append(makeComponentsjsSource());
			} else if (type.equals("<ThemeSource>")) {
				result.append(makeThemeSource());
			} else if (type.equals("<CustomContent>")) {
				result.append("\n<!-- CustomContent -->" + themeObjectSource.getContent());
			} else if (type.equals("<BackendjsSource>")) {
				result.append(makeBackendjsSource());
			} else if (type.equals("<SourceTags>")) {
				result.append(makeSourceTags(themeObjectSource.getSource()));
			} else if (StrUtil.startWith(type, "<Include:")) {
				result.append(makeInclude(type));
			}
		}
		return result;
	}

}
